package processus;

import java.util.ArrayList;
import java.util.Collections;

public class FileDeRequetes {
    
    protected int pidLocal; // Pid  du père gérant cette file
    protected int nbVoisins;
    protected int nbReplies;
    protected ArrayList<Requete> listeRequetes = new ArrayList<Requete>();

    public FileDeRequetes(int pidLocal, int nbPeres) {
        this.pidLocal = pidLocal;
        this.nbVoisins = nbPeres - 1;
    }
    
    /**
     * Requête de demande d'entrée en section critique (émise ou reçue)
     */
    public void requestSentOrReceived(int pid, int estampille) {
        
        // On stocke la requête
        Requete req = new Requete(pid, estampille);
        listeRequetes.add(req);
        
        // On tri la nouvelle liste dans l'ordre croissant
        Collections.sort(listeRequetes);
        
        // Si père courant qui envoi la requête, on initialise nbReplies à 0
        if(pid == pidLocal) {
            nbReplies = 0;
        }
    }
    
    /**
     * Réception d'une réponse à notre requête
     */
    public void replyReceived() {
        nbReplies++;
    }
    
    /**
     * Fin de section critique émise ou reçue
     */
    public void releaseSentOrReceived() {
        listeRequetes.remove(0);
    }
    
    /**
     * Si le père courant peut entrer en section critique (premier de la liste et tous les replies reçues)
     */
    public boolean canEnterSectionCritique() {

        // Si on a reçu une réponse de tous les voisins
        if(nbReplies == nbVoisins) {
            // Si le père courant est en premier dans la liste
            if(listeRequetes.get(0).getPid() == pidLocal) {
                return true;
            }
        }
        
        return false;
    }
    
    // Classe requête
    public class Requete implements Comparable<Requete> {
        
        protected int  pid;
        protected int  estampille;

        public Requete(int pid, int estampille) {
            this.pid = pid;
            this.estampille = estampille;
        }

        public int getPid() {
            return pid;
        }

        public int getEstampille() {
            return estampille;
        }
        
        @Override
        public int compareTo(Requete req2) { 
            
            // Si estampille courante plus faible
            if(estampille < req2.estampille) {
                return -1;
            }
            
            // Si estampilles égales
            if(estampille == req2.estampille) {
                if(pid < req2.pid) {
                    return -1;
                }
                if(pid > req2.pid) {
                    return 1;
                }
            }
            
            // Si estampille courante plus élevée
            if(estampille > req2.estampille) {
                return 1;
            }
            
            // Mêmes estampilles et pids
            return 0;
        }

        @Override
        public String toString() {
            return "{" + estampille + ','+pid+'}';
        }
        
   } 
    
}